package blackstar.plugin.monitor.reporter;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author Ray (ayufox@gmail.com)
 */
public class AsynResultReporter implements ResultReporter
{
	private final static Log LOGGER = LogFactory.getLog(AsynResultReporter.class);

	private ResultReporter targetResultReporter;

	private ExecutorService executorService;

	public AsynResultReporter(ResultReporter targetResultReporter,
			ExecutorService executorService)
	{
		super();
		this.targetResultReporter = targetResultReporter;
		this.executorService = executorService;
	}

	public AsynResultReporter(ResultReporter targetResultReporter,
			int threadCount)
	{
		super();
		this.targetResultReporter = targetResultReporter;
		this.executorService = Executors.newFixedThreadPool(threadCount);
	}

	public AsynResultReporter(ResultReporter targetResultReporter,
			int corePoolSize, int maximumPoolSize, long keepAliveTime,
			TimeUnit unit, BlockingQueue<Runnable> workQueue,
			ThreadFactory threadFactory, RejectedExecutionHandler handler)
	{
		super();
		this.targetResultReporter = targetResultReporter;
		this.executorService = new ThreadPoolExecutor(corePoolSize,
				maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory,
				handler);
	}

	public AsynResultReporter(ResultReporter targetResultReporter,
			int corePoolSize, int maximumPoolSize)
	{
		this(targetResultReporter, corePoolSize, maximumPoolSize, 1000);
	}

	public AsynResultReporter(ResultReporter targetResultReporter,
			int corePoolSize, int maximumPoolSize, int queueSize)
	{
		super();
		this.targetResultReporter = targetResultReporter;
		this.executorService = new ThreadPoolExecutor(corePoolSize,
				maximumPoolSize, 30, TimeUnit.MINUTES,
				new ArrayBlockingQueue<Runnable>(queueSize));
	}

	public void report(final ReportData data)
	{
		this.executorService.execute(new Runnable()
		{
			public void run()
			{
				targetResultReporter.report(data);
			}
		});
	}

	public void destroy()
	{
		try
		{
			this.executorService.awaitTermination(5, TimeUnit.SECONDS);
		} catch (InterruptedException e)
		{
			LOGGER.error("shutdown ExecutorService Failed", e);
		}
	}
}
